package com.utils;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 关于日期类型转换,获取数据库服务器的时间等的一些通用方法;
 * <ul>
 * <li>1.1</li>
 * <li>增加常用的日期格式变量</li>
 * <li>增加日志记录,级别为debug</li>
 * <li>优化部分代码</li>
 * </ul>
 *
 * @version 1.1
 */
public class DateUtil {
	static Logger log = LoggerFactory.getLogger(DateUtil.class);

	public static final String YYYY_MM_DD_HH_MM_SS_SSS = "yyyy-MM-dd HH:mm:ss:sss";
	public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
	public static final String YYYY_MM_DD_HH_MM = "yyyy-MM-dd HH:mm";
	public static final String YYYY_MM_DD_HH = "yyyy-MM-dd HH";
	public static final String YYYY_MM_DD = "yyyy-MM-dd";
	public static final String YYYY_MM = "yyyy-MM";
	public static final String YYYY = "yyyy";
	public static final String HH_MM_SS_SSS = "HH:mm:ss:sss";
	public static final String HH_MM_SS = "HH:mm:ss";
	public static final String HH24MMSS = "HHmmss";
	public static final String HH_MM = "HH:mm";
	public static final String HH = "HH";

	public static final String PATTERN_yyyyMMddHHmmssSSS = "yyyyMMddHHmmssSSS";
	public static final String PATTERN_yyyyMMddHHmmss = "yyyyMMddHHmmss";
	public static final String PATTERN_yyyyMMdd = "yyyyMMdd";
	public static final String PATTERN_YYYYMMDD = "yyyyMMdd";
	public static final String PATTERN_yyyyMM = "yyyyMM";
	public static final String PATTERN_yyyy = "yyyy";

	/**
	 * 获取整型时间
	 * @param date 传入当前时间
	 * @return 返回LONG型的时间
	 */
	public synchronized static Long dateToFullLong(Date date) {
		String date2String = null;
		try {
			if (date == null){
				return null;
			}

			date2String = date2String(date, PATTERN_yyyyMMddHHmmssSSS);
		} catch (Exception e) {
			log.debug("获取整形时间出错!", e);
		}
		return Long.parseLong(date2String);
	}

	/**
	 * 获取当前时间的INT型数据
	 * @param date 当前时间
	 * @return 返回INT型的时间
	 */
	public synchronized static Integer dateToyyyyMMInteger(Date date) {
		String date2String = null;
		try {
			if (date == null){
				return null;
			}

			date2String = date2String(date, PATTERN_yyyyMM);
		} catch (Exception e) {
			log.debug("获取当前时间的INT型数据出错!", e);
		}
		return Integer.parseInt(date2String);
	}

	/**
	 * 获取当前年度 INT型
	 * @param date 当前时间
	 * @return 返回年度INT
	 */
	public synchronized static Integer dateToyyyyInteger(Date date) {
		String date2String = null;
		try {
			if (date == null){
				return null;
			}

			date2String = date2String(date, PATTERN_yyyy);
		} catch (Exception e) {
			log.debug("获取当前年度 INT型 出错!", e);
		}
		return Integer.parseInt(date2String);
	}

	/**
	 * 将特定的字符串日期转化成日期类型 <br />
	 * 1.需要格式化的字符型日期str <br />
	 * 2.可判断的格式为：yyyy-MM-dd和yyyy-MM-dd HH:mm:ss; <br />
	 * 得到日期型数据
	 *
	 * @param str
	 *            需要处理的日期型字符串
	 * @return 返回一个日期类型的对象
	 * @see java.util.Date
	 * @see java.text.SimpleDateFormat
	 * @see java.text.ParseException
	 *
	 */
	public static Date str2Date(String str) {
		str=str.replace(".0", "");
		String formatStr = YYYY_MM_DD;
		String reg1 = "^\\d{4}-\\d{1,2}-\\d{1,2}$";
		String reg2 = "^\\d{4}-\\d{1,2}-\\d{1,2}\\s+\\d{1,2}:\\d{1,2}:\\d{1,2}$";
		String reg3 = "^\\d{4}-\\d{1,2}";
		String reg4 = "^\\d{4}\\d{1,2}";
		if(str.matches(reg1)){
			formatStr = YYYY_MM_DD;
		}
		if(str.matches(reg2)){
			formatStr = YYYY_MM_DD_HH_MM_SS;
		}
		if(str.matches(reg3)){
			formatStr = YYYY_MM;
		}

		if(str.matches(reg4)){
			formatStr = PATTERN_yyyyMM;
		}

		SimpleDateFormat sdf = new SimpleDateFormat(formatStr);

		try {
			if (!StringUtil.isEmpty(str)) {
				str = StringUtil.str2Trim(str);
				Date date = sdf.parse(str);
				return date;
			}
		} catch (ParseException e) {
			e.printStackTrace();
			log.debug("字符串日期转化成日期类型时出错!", e);
		} finally {
			sdf = null;
		}
		return null;
	}

	/**
	 * 将特定的字符串日期转化成日期类型 <br />
	 * 1.需要格式化的字符型日期str <br />
	 * 2.可判断的格式为：yyyy-MM-dd和yyyy-MM-dd HH:mm:ss; <br />
	 * 得到日期型数据
	 *
	 * @param str
	 *            需要处理的日期型字符串
	 * @param formatStr
	 *            需要处理成什么格式
	 * @return 返回一个日期类型的对象
	 * @see java.util.Date
	 * @see java.text.SimpleDateFormat
	 * @see StringUtil
	 * @see java.text.ParseException
	 *
	 */
	public static Date str2Date(String str, String formatStr) {
		SimpleDateFormat sdf = new SimpleDateFormat(formatStr);

		try {
			if (!StringUtil.isEmpty(str)) {
				str = StringUtil.str2Trim(str);
				Date date = sdf.parse(str);
				return date;
			}
		} catch (ParseException e) {
			log.error("字符串日期转化成日期类型时出错!", e);
		} finally {
			sdf = null;
		}
		return null;
	}

	/**
	 * 将日期型转化为特定格式的字符型日期 <br />
	 * 1.需要的日期date <br />
	 * 2.需要格式化成什么样的字符串formatStr--(yyyy-MM-dd HH:mm:ss); <br />
	 * 得到需要的字符串型日期
	 *
	 * @param date
	 *            需要处理的日期
	 * @param formatStr
	 *            需要处理成什么样的格式
	 * @return 返回一个日期型的日期类型
	 * @see java.text.SimpleDateFormat
	 * @see java.util.Date
	 * @see Exception
	 */
	public static String date2String(Date date, String formatStr) {
		SimpleDateFormat sdf = null;
		String formatDate = null;
		try {
			if (date != null) {
				sdf = new SimpleDateFormat(formatStr);
				formatDate = sdf.format(date);
				return formatDate;
			}
		} catch (Exception e) {
			log.debug("日期型转化为特定格式的字符型时出错!!", e);
		} finally {
			sdf = null;
			formatDate = null;
		}
		return null;
	}

	/**
	 * 获取日期中的年
	 *
	 * @param date 需要提取的日期
	 * @return 返回年
	 * @throws Exception
	 */
	public static Integer getYear(Date date) throws Exception {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);

		int year = cal.get(Calendar.YEAR);
		return year;
	}

	/**
	 * 获取日期中的月
	 *
	 * @param date 需要提取的日期
	 * @return 返回月
	 * @throws Exception
	 */
	public static Integer getMonth(Date date) throws Exception {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);

		int re = cal.get(Calendar.MONTH);
		return re;
	}

	/**
	 * 获取日期中的日
	 *
	 * @param date 需要提取的日期
	 * @return 返回日
	 * @throws Exception
	 */
	public static Integer getDate(Date date) throws Exception {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);

		int re = cal.get(Calendar.DATE);
		return re;
	}

	/**
	 * 获取日期中的时
	 *
	 * @param date 需要提取的日期
	 * @return 返回时
	 * @throws Exception
	 */
	public static Integer getHour(Date date) throws Exception {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);

		int re = cal.get(Calendar.HOUR);
		return re;
	}

	/**
	 * 获取日期中的时
	 *
	 * @param date 需要提取的日期
	 * @return 返回时
	 * @throws Exception
	 */
	public static Integer getMinutes(Date date) throws Exception {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);

		int re = cal.get(Calendar.MINUTE);
		return re;
	}

	/**
	 * 获取日期中的秒
	 *
	 * @param date 需要提取的日期
	 * @return 返回秒
	 * @throws Exception
	 */
	public static Integer getSeconds(Date date) throws Exception {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);

		int re = cal.get(Calendar.SECOND);
		return re;
	}

	/**
	 * 获取日期中的星期
	 *
	 * @param date 需要提取的日期
	 * @return 返回星期
	 * @throws Exception
	 */
	public static Integer getWeek(Date date) throws Exception {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);

		int re = cal.get(Calendar.WEEK_OF_MONTH);
		return re;
	}


	/**
	 * 获取时间差
	 * 注:当传入的时间差,不成立时,取最小值
	 *
	 * @param dateStr 返回相应的时间
	 * @param dateType 0全部返回 1年 2月 3日 4时 5分 6秒 null空视为全部
	 * @return
	 * @throws Exception
	 */
	public static String getDaysDiff(Date nowDate, String dateStr, Integer dateType) throws Exception {
		Date myDate = str2Date(dateStr);

		if (nowDate == null) {
			nowDate = new Date();
		}

		long yd = 1000 * 24 * 60 * 60 * 30 * 12;// 一年的毫秒数
		long md = 1000 * 24 * 60 * 60 * 30;// 一月的毫秒数
		long nd = 1000 * 24 * 60 * 60;// 一天的毫秒数
		long nh = 1000 * 60 * 60;// 一小时的毫秒数
		long nm = 1000 * 60;// 一分钟的毫秒数
		long ns = 1000;// 一秒钟的毫秒数

		long diff;
		long year = 0;
		long month = 0;
		long day = 0;
		long hour = 0;
		long min = 0;
		long sec = 0;

		// 获得两个时间的毫秒时间差异
		diff = myDate.getTime() - nowDate.getTime();
		year = diff / yd;// 计算差多少天
		month = diff / md;// 计算差多少天
		day = diff / nd;// 计算差多少天
		hour = diff % nd / nh + day * 24;// 计算差多少小时
		min = diff % nd % nh / nm + day * 24 * 60;// 计算差多少分钟
		sec = diff % nd % nh % nm / ns;// 计算差多少秒

		String reStr = null;

		switch (dateType) {
			case 0:// 全部
				reStr = year + "年" + month + "月" + day + "日" + hour + "时" + sec + "分" + min + "秒";
				break;
			case 1: // 年
				if (year == 0) {
					reStr = getDaysDiff(nowDate, dateStr, (dateType + 1));
				} else {
					reStr = year + "";
				}
				break;
			case 2: // 月
				if (month == 0) {
					reStr = getDaysDiff(nowDate, dateStr, (dateType + 1));
				} else {
					reStr = month + "";
				}
				break;
			case 3: // 日
				if (day == 0) {
					reStr = getDaysDiff(nowDate, dateStr, (dateType + 1));
				} else {
					reStr = day+"";
				}
				break;
			case 4: // 时
				if (hour == 0) {
					reStr = getDaysDiff(nowDate, dateStr, (dateType + 1));
				} else {
					reStr = hour + "";
				}
				break;
			case 5: // 分
				if (sec == 0) {
					reStr = getDaysDiff(nowDate, dateStr, (dateType + 1));
				} else {
					reStr = sec + "";
				}
				break;
			case 6: // 秒
				if (min == 0) {
					reStr = getDaysDiff(nowDate, dateStr, (dateType + 1));
				} else {
					reStr = min + "";
				}
				break;
			default:
				break;
		}
		return reStr;
	}

	public static Integer getDayDiff(Date time,Date diffTime) throws Exception {
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
		String tempTime = simpleDateFormat.format(diffTime);
		return Math.abs(Integer.parseInt(DateUtil.getDaysDiff(new Date(), tempTime, 3)))-1;
	}

	/**
	 * long时间转为特定格式
	 * <ul>
	 * <li>林啸虎 2015年10月30日 新建</li>
	 * </ul>
	 *
	 * @param longDate 需要格式的时间
	 * @param format 格式化
	 * @return
	 * @throws Exception
	 */
	public static String dateFormat(Object longDate,String format) throws Exception {
		SimpleDateFormat date = new SimpleDateFormat(format);
		String str = date.format(longDate);
		return str;
	}

    /**
     * <ul>
     *  <li>sslf 2016年3月3日下午4:55:20 新建<li>
     * </ul>
     * 获取今天的开始时间
     * @return
     */
    public static String getToDay(){
        String result;

        Calendar cal   =   Calendar.getInstance();
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.MILLISECOND, 0);
        result = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss").format(cal.getTime());

        return result;
    }

	/**
	 * 获取今天的结束时间
	 * @return
	 */
	public static String getEndTime() {
		String result = "";
		Calendar todayEnd = Calendar.getInstance();
		todayEnd.set(Calendar.HOUR_OF_DAY, 23);
		todayEnd.set(Calendar.MINUTE, 59);
		todayEnd.set(Calendar.SECOND, 59);
		todayEnd.set(Calendar.MILLISECOND, 999);
		result = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(todayEnd.getTime());
		return result;
	}
	/**
     * <ul>
     *  <li>sslf 2016年3月3日下午5:03:20 新建<li>
     * </ul>
     * 得到几天前的开始时间
     * @param num
     * @return
     */
    public static Date getAfterBeginTime(int num){
        Calendar cal = Calendar.getInstance();

        cal.add(Calendar.DATE,   -num);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.MILLISECOND, 0);

        return cal.getTime();
    }

	/**
	 * 设置num加减天数
	 * @param num
	 * @return
	 */
	public static Date getTimeIsDayByNum(int num){
		Calendar cal = Calendar.getInstance();

		cal.add(Calendar.DATE,   num);
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.MILLISECOND, 0);

		return cal.getTime();
	}

	public static Date getSettBegin(Date date){
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.DATE,   -1);
		cal.set(Calendar.HOUR_OF_DAY, 00);
		cal.set(Calendar.MINUTE, 00);
		cal.set(Calendar.SECOND, 00);
		cal.set(Calendar.MILLISECOND, 000);

		return cal.getTime();
	}

	public static Date getSettEnd(Date date){
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.DATE,   -1);
		cal.set(Calendar.HOUR_OF_DAY, 23);
		cal.set(Calendar.MINUTE, 59);
		cal.set(Calendar.SECOND, 59);
		cal.set(Calendar.MILLISECOND, 0);

		return cal.getTime();
	}


    /**
     * <ul>
     *  <li>sslf 2016年3月7日下午1:55:48 新建<li>
     * </ul>
     * 得到几天前的结束时间
     * @param num
     * @return
     */
    public static Date getAfterEndTime(int num){
        Calendar cal = Calendar.getInstance();

        cal.add(Calendar.DATE,   -num);
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.SECOND, 59);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.MILLISECOND, 999);

        return cal.getTime();
    }


    /**
     * <ul>
     *  <li>sslf 2016年3月7日上午10:02:02 新建<li>
     * </ul>
     * 根据传入的年份和月份得到该月份的开始时间
     * @param year 目标年份
     * @param month 目标月份
     * @return
     */
    public static Date getBeginTimeOfMonth(Integer year, Integer month){
        Calendar calendar = Calendar.getInstance();

        if (year == null){
            year = calendar.get(Calendar.YEAR);
        }

        if (month == null){
            month = calendar.get(Calendar.MONTH);
        } else {
            month -= 1;
        }

        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH, month);
        calendar.set(Calendar.DATE, 1);

        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.MILLISECOND, 0);

        return calendar.getTime();
    }


    /**
     * <ul>
     *  <li>sslf 2016年3月7日上午10:23:02 新建<li>
     * </ul>
     * 根据传入的年份和月份得到该月份的结束时间
     * @param year
     * @param month
     * @return
     */
    public static Date getEndTimeOfMonth(Integer year, Integer month){
        Calendar calendar = Calendar.getInstance();

        if (year == null){
            year = calendar.get(Calendar.YEAR);
        }

        if (month == null){
            month = calendar.get(Calendar.MONTH);
        }

        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH, month);
        calendar.set(Calendar.DATE, 0);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.MILLISECOND, 999);

        return calendar.getTime();
    }

    /**
     * 获取当前时间的字符串
     * @return
     */
    public static String getDateStr(){
        String result = null;
        try {
            result = DateUtil.dateFormat(new Date(), "yyyyMMddhhmmssS");
        } catch (Exception e) {
            e.printStackTrace();
        }

        return result;
    }

    /**
     * 获取xx之后xxx的时间
     * @param dateStr 时间节点字符串
     * @param type 单位 y（年）、M（月）、d（日）、h（时）、m（分）、s（秒）
     * @param num
     * @return
     */
    public static Date getAfterDate(String dateStr,String type,int num){
        Date result = null;

        Date targetDate = str2Date(dateStr);

        return getAfterDate(targetDate, type, num);
    }

    public static Date getAfterDate(Date targetDate,String type, int num) {
        Date result;Calendar calendar = Calendar.getInstance();
        calendar.setTime(targetDate);

        switch (type){
            case "y" : {
                calendar.add(Calendar.YEAR,num);
                break;
            }
            case "M" : {
                calendar.add(Calendar.MONTH,num);
                break;
            }
            case "d" : {
                calendar.add(Calendar.DATE,num);
                break;
            }
            case "h" : {
                calendar.add(Calendar.HOUR_OF_DAY,num);
                break;
            }
            case "m" : {
                calendar.add(Calendar.MINUTE,num);
                break;
            }
            case "s" : {
                calendar.add(Calendar.SECOND,num);
                break;
            }
        }

        result = calendar.getTime();

        return result;
    }



    /**
     * 获取当前时间
     * @param type
     * @param num
     * @return
     */
    public static Date getCurrAfterDate(String type,int num){
        return getAfterDate(new Date(), type,num);
    }

	/**
 　　* 判断时间是否在时间段内 *
 　　* @param date
 　　* 当前时间 yyyy-MM-dd HH:mm:ss
 　　* @param strDateBegin
 　　* 开始时间 00:00:00
 　　* @param strDateEnd
 　　* 结束时间 00:05:00
 　　* @return
 　　*/
	public static boolean isInDate(Date date, String strDateBegin,
									 String strDateEnd) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String strDate = sdf.format(date);
		// 截取当前时间时分秒
		int strDateH = Integer.parseInt(strDate.substring(11, 13));
		int strDateM = Integer.parseInt(strDate.substring(14, 16));
		int strDateS = Integer.parseInt(strDate.substring(17, 19));

		// 截取开始时间时分秒
		int strDateBeginH = Integer.parseInt(strDateBegin.substring(0, 2));
		int strDateBeginM = Integer.parseInt(strDateBegin.substring(3, 5));
		int strDateBeginS = Integer.parseInt(strDateBegin.substring(6, 8));

		// 截取结束时间时分秒
		int strDateEndH = Integer.parseInt(strDateEnd.substring(0, 2));
		int strDateEndM = Integer.parseInt(strDateEnd.substring(3, 5));
		int strDateEndS = Integer.parseInt(strDateEnd.substring(6, 8));

		if ((strDateH >= strDateBeginH && strDateH <= strDateEndH)) {
			// 当前时间小时数在开始时间和结束时间小时数之间
			if (strDateH > strDateBeginH && strDateH < strDateEndH) {
				return true;
				// 当前时间小时数等于开始时间小时数，分钟数在开始和结束之间
			} else if (strDateH == strDateBeginH && strDateM >= strDateBeginM
						&& strDateM <= strDateEndM) {
				return true;
				// 当前时间小时数等于开始时间小时数，分钟数等于开始时间分钟数，秒数在开始和结束之间
			} else if (strDateH == strDateBeginH && strDateM == strDateBeginM
						&& strDateS >= strDateBeginS && strDateS <= strDateEndS) {
				return true;
			}

			// 当前时间小时数大等于开始时间小时数，等于结束时间小时数，分钟数小等于结束时间分钟数
			else if (strDateH >= strDateBeginH && strDateH == strDateEndH
					&& strDateM <= strDateEndM){
				return true;
				// 当前时间小时数大等于开始时间小时数，等于结束时间小时数，分钟数等于结束时间分钟数，秒数小等于结束时间秒数
			} else if (strDateH >= strDateBeginH && strDateH == strDateEndH
					&& strDateM == strDateEndM && strDateS <= strDateEndS) {
				return true;
			}else{
				return false;
			}
		} else {
			return false;
		}
	}

    public static void main(String[] args) throws Exception {

//		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//		String tempTime = simpleDateFormat.format(new Date());
//		tempTime = "2018-02-12 17:35:53";
//		Integer t = 0;
//		try {
//			String ti = DateUtil.getDaysDiff(new Date(),tempTime,3);
//			if(ti != null){
//				t = Integer.parseInt(ti);
//			}
//		} catch (Exception e) {
//			e.printStackTrace();
//		}
//
//		System.out.println(Math.abs(t));
		Map<String,Long> map = new HashMap<>();
		map.put("123",154648464L);
		for (Map.Entry<String,Long> entry : map.entrySet()){

			long a = (long)(entry.getValue()*(0.1/100));
			System.out.println(a);
		}
	}


	public static String formatTime(Long ms) {
		Integer ss = 1000;
		Integer mi = ss * 60;
		Integer hh = mi * 60;
		Integer dd = hh * 24;

		long day = ms / dd;
		long hour = (ms - day * dd) / hh;
		long minute = (ms - day * dd - hour * hh) / mi;
		long second = (ms - day * dd - hour * hh - minute * mi) / ss;

		StringBuilder sb = new StringBuilder();
		if (day > 0) {
			sb.append(day).append("天");
		}
		if (hour > 0) {
			sb.append(hour).append("小时");
		}
		if (minute > 0) {
			sb.append(minute).append("分");
		}
		if (second > 0) {
			sb.append(second).append("秒");
		}
		return sb.toString();
	}

}
